Test HTTP Requests Tools Blog PHP Quiz API Log In With Github
Test HTTP Requests Tools Blog PHP Quiz API Log In With Github
« Return to the tutorials list
We have updated the website and our policies to make sure your privacy rights and security are respected.
Click here to learn more about the way our website handles your data.

Remove this message.

You can read this article in: English :: EspaƱol

How to mix PNG files together while preserving their transparency, using PHP and GD Library

Daniel Gheorghe Difficulty: 30 / 50 Tweet

Today we're going to learn how to use the GD Library to merge 3 or more png files into one while preserving transparency

We start with 3 png files that look like the ones below and what we want to achieve is a fourth image that represents the 3 initial png files one on top of the other, while preserving their transparency.

The tricky part when mixing png files is keep the transparency or alpha levels intact. To do that you need to know that when creating an image resource in PHP you have to make it "remember" the alpha state and fill the new resource with a transparency by using the imagecolorallocatealpha() function.

Enough theory ... here's the code:

    
        <?php 
            //define the width and height of our images
            define("WIDTH", 200);
            define("HEIGHT", 200);

            $dest_image = imagecreatetruecolor(WIDTH, HEIGHT);

            //make sure the transparency information is saved
            imagesavealpha($dest_image, true);

            //create a fully transparent background (127 means fully transparent)
            $trans_background = imagecolorallocatealpha($dest_image, 0, 0, 0, 127);

            //fill the image with a transparent background
            imagefill($dest_image, 0, 0, $trans_background);

            //take create image resources out of the 3 pngs we want to merge into destination image
            $a = imagecreatefrompng('1.png');
            $b = imagecreatefrompng('2.png');
            $c = imagecreatefrompng('3.png');

            //copy each png file on top of the destination (result) png
            imagecopy($dest_image, $a, 0, 0, 0, 0, WIDTH, HEIGHT);
            imagecopy($dest_image, $b, 0, 0, 0, 0, WIDTH, HEIGHT);
            imagecopy($dest_image, $c, 0, 0, 0, 0, WIDTH, HEIGHT);

            //send the appropriate headers and output the image in the browser
            header('Content-Type: image/png');
            imagepng($dest_image);

            //destroy all the image resources to free up memory
            imagedestroy($a);
            imagedestroy($b);
            imagedestroy($c);
            imagedestroy($dest_image);
    ?>
    

The image you see on the right is the result that you should also see in your browser if everything went well with your code. Now let's recap what you've learned:

1. PHP is not limited to HTML output by using its image functions (GD Library) you can also manipulate/create images.

2. When creating PNG files with php you have to remember to set the correct transparency levels. Otherwise you will end up with an ugly black background

3. When playing with image resources in php you have to remember to always free up memory by destroying those image resources

Update: February 20th - Proper Image Manipulation in modern PHP applications

Since 2014 when this article was published, PHP has evolved into a modern language with namespaces, packages and other great features that all modern PHP apps should be using.

Because many people use this guide as a reference, I'm updating it with how I think this should be done today. A very easy way to merge PNG files and preserve transparency using a package called intervention/image maintained and perfectly documented by Oliver Vogel.

Of course, we start by requiring the package in our application: composer require intervention/image

Once that's done, you can achieve the same functionality as above in a beautiful one-liner:


<?php
    require 'vendor/autoload.php';
    use Intervention\Image\ImageManagerStatic as Image;

    Image::canvas(200, 200)
        ->insert(__DIR__ . '/1.png')
        ->insert(__DIR__ . '/2.png')
        ->insert(__DIR__ . '/3.png')
        ->save(__DIR__ . '/out.png');
?>